package sparrowGui.components
{
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.utils.getQualifiedClassName;
	
	import sparrowGui.components.item.ItemFactory;
	import sparrowGui.components.item.SButton;
	import sparrowGui.data.AlertVO;
	import sparrowGui.event.AlertEvent;
	import sparrowGui.i.IItemFactory;
	import sparrowGui.uiStyle.UIStyleMgr;
	
	/**
	 * 队列警告弹窗管理.
	 * 能弹窗组件是单例的,即当场景只会弹一个,如果是多个提示信息会轮流弹窗
	 * 
	 * 例子如下
	 * 
	 * // 使用前先初始单例
	 *  new QueueAlert(this);
		
		btn.addEventListener(MouseEvent.CLICK,onBtnClick);
		function onBtnClick(e:MouseEvent):void
		{
			QueueAlert.getIns().alertYesNo("asd22f",back);
		}
		
		function back(e:AlertEvent):void
		{
			trace(e);
		}
	 * 
	 * @author Pelephone
	 * @website http://cnblogs.com/pelephone
	 */
	public class QueueAlert
	{
		protected static var instance : QueueAlert; 
		/**
		 * 警告窗数据队列,这里用静态.
		 */
		private var alertQueue:Array;
		/**
		 * 默认警告窗皮肤
		 */
		private var _alt:SAlert;
		
		/**
		 * 项创建工厂
		 */
		private var btnFactory:IItemFactory;
		/**
		 * 默认警告窗皮肤
		 */
		private var defaultSkin:DisplayObject;
		/**
		 * 默认按钮皮肤
		 */
		private var _defaultBtnCls:Class;
		
		/**
		 * 通过提示窗皮肤和你容器构造警告窗体
		 * @param showParent 显示到容器
		 * @param alertUiVars 警告窗皮肤变量
		 * @param itemFactory 子项工厂，用于创建子项和子项皮肤，工厂里还有缓存的功能
		 */
		public function QueueAlert(showParent:DisplayObjectContainer=null
								   ,alertUiVars:Object=null,itemFactory:IItemFactory=null)
		{
			if (instance != null) throw Error("此单例已经存在了");
			
			alertQueue = [];
			btnFactory = itemFactory || new ItemFactory(SButton,"txtItem");
			
			defaultSkin = UIStyleMgr.getIns().createSkinUI("alert");
			_alt = new SAlert(showParent,defaultSkin,btnFactory);
			
			instance = this;
		}
		
		//获取单例
		public static function getIns():QueueAlert {
			if (instance == null) instance = new QueueAlert( );
			return instance;
		}
		
		/**
		 * 通过变量弹出提示信息
		 * @param vars
		 */
		public function alertVar(vars:AlertVO):void
		{
			// 如果提示队列还有未关闭的数据就本弹窗信息添加到队列,反之马上弹窗
			if(_alt.isShow)
			{
				alertQueue.push(vars);
				return;
			}
			alertShow(vars);
		}
		
		/**
		 * 马上跟据变量弹窗
		 * @param vars
		 */
		private function alertShow(vars:AlertVO):void
		{
			// 替换警告窗提示
			if(vars.skin && _alt.skin!=vars.skin)
				_alt.reCreate(vars.skin);
			else if(!vars.skin && defaultSkin	&& _alt.skin!=defaultSkin)
				_alt.reCreate(defaultSkin);
			
			// 替换警告窗按钮皮肤
			if(vars.btnSkinCls!=null && 
				getQualifiedClassName(vars.btnSkinCls)!=getQualifiedClassName(btnFactory.itemSkinClass))
				btnFactory.itemSkinClass = vars.btnSkinCls;
			else if(!vars.skin && defaultBtnCls!=null && 
				getQualifiedClassName(btnFactory.itemSkinClass) != getQualifiedClassName(defaultBtnCls))
				btnFactory.itemSkinClass = defaultBtnCls;
			
			// 如果有输入窗就设置默认输入窗文字
			if(_alt.txtInput && vars.defaultInput)
				_alt.txtInput.text = String(vars.defaultInput);
			
			// 监听界面更新
			if(vars.onUpdate!=null)
				_alt.addEventListener(AlertEvent.ALERT_UPDATE,vars.onUpdate);
			
			_alt.autoClose = vars.autoClose;
			
			_alt.show(vars.alertData,vars.btnStr,vars.onClose);
			_alt.addEventListener(AlertEvent.ALERT_CLOSE,onAlertClose);
			
			vars.dispose();
		}
		
		/**
		 * 窗体关闭时数值还有警告数据就提示下一项
		 * @param e
		 */
		private function onAlertClose(e:AlertEvent):void
		{
			if(!_alt.autoClose) return;
			callNext();
		}
		
		/**
		 * 提示下一组警告信息
		 */
		public function callNext():void
		{
			_alt.autoClose = true;
			_alt.removeTypeListeners(AlertEvent.ALERT_CLOSE);
			_alt.removeTypeListeners(AlertEvent.ALERT_UPDATE);
			if(!alertQueue.length) return;
			var alVars:AlertVO = alertQueue.shift();
			alertShow(alVars);
		}
		
		/**
		 * 只有一个确定按钮的提示框
		 * @param txt 弹窗文本内容
		 * @param backFun 点击按钮时返回接收函数
		 */
		public function alertOk(txt:String,backFun:Function=null):AlertVO
		{
			return alert(txt,backFun,"确定");
		}
		
		/**
		 * 选择按钮提示框
		 * @param txt 弹窗文本内容
		 * @param backFun 点击按钮时返回接收函数
		 */
		public function alertYesNo(txt:String,backFun:Function=null):AlertVO
		{
			return alert(txt,backFun,"确定|取消");
		}
		
		/**
		 * 输入文本弹窗
		 * @param txt 弹窗文本内容
		 * @param backFun 点击按钮时返回接收函数
		 * @param defaultStr 默认输入文本里面的文字
		 */
		public function alertInput(txt:String,backFun:Function=null,defaultStr:String="请输入数字"):AlertVO
		{
			var btnStr:String = "确定";
			if(!_alt.isShow)
			{
				_alt.show(txt,btnStr,backFun);
				_alt.addEventListener(AlertEvent.ALERT_CLOSE,onAlertClose);
				return null;
			}
			var vars:AlertVO =  new AlertVO();
			vars.alertData = txt;
			vars.defaultInput = defaultStr;
			vars.onClose = backFun;
			vars.btnStr = btnStr;
			alertVar(vars);
			return vars;
		}
		
		/**
		 * 加按钮参数的警告
		 * @param txt 弹窗文本内容
		 * @param backFun 点击按钮时返回接收函数
		 * @param btnStr 按钮上的文字，用"|"分隔按钮
		 */
		public function alert(txt:String,backFun:Function=null,btnStr:String="确定"):AlertVO
		{
			if(!_alt.isShow)
			{
				_alt.show(txt,btnStr,backFun);
				_alt.addEventListener(AlertEvent.ALERT_CLOSE,onAlertClose);
				return null;
			}
			var vars:AlertVO =  new AlertVO();
			vars.alertData = txt;
			vars.onClose = backFun;
			vars.btnStr = btnStr;
			alertVar(vars);
			return vars;
		}
		
		/**
		 * 警告组件
		 * @return 
		 */
		public function get alertComponent():SAlert
		{
			return _alt;
		}
		
		public function get defaultBtnCls():Class
		{
			return _defaultBtnCls;
		}
		
		public function set defaultBtnCls(value:Class):void
		{
			_defaultBtnCls = value;
		}
	}
}